<?php
/**
 * 配置类模块
 * 
 * @author jlpay-sdk-php
 * @version 1.0.0
 */

namespace JLPay\Core;

use Exception;
use JLPay\Utils\SmUtils;

/**
 * 配置异常类
 */
class ConfigException extends Exception
{
    //
}

/**
 * 机构配置类
 */
class OrgConfig
{
    /**
     * AppID
     * @var string
     */
    public $appId;
    
    /**
     * 请求地址
     * @var string
     */
    public $url;
    
    /**
     * 机构私钥（PEM格式）
     * @var string
     */
    public $orgPriKey;
    
    /**
     * 机构公钥（PEM格式）
     * @var string
     */
    public $orgPubKey;
    
    /**
     * 嘉联公钥（PEM格式）
     * @var string
     */
    public $jlpayPubKey;
    
    /**
     * 是否校验机构号
     * @var bool
     */
    public $verifyOrgNo;
    
    /**
     * 是否校验商户号
     * @var bool
     */
    public $verifyMerchNo;
    
    /**
     * 加密算法
     * @var string
     */
    public $cryptoAlg;
    
    /**
     * 是否自动加密
     * @var bool
     */
    public $autoEncrypt;
    
    /**
     * 是否自动解密
     * @var bool
     */
    public $autoDecrypt;
    
    /**
     * 连接超时时间（毫秒）
     * @var int
     */
    public $connectTimeout;
    
    /**
     * 读取超时时间（毫秒）
     * @var int
     */
    public $readTimeout;
    
    /**
     * 机构私钥（16进制）
     * @var string
     */
    public $orgPriKeyHex;
    
    /**
     * 机构公钥（16进制）
     * @var string
     */
    public $orgPubKeyHex;
    
    /**
     * 嘉联公钥（16进制）
     * @var string
     */
    public $jlpayPubKeyHex;
    
    /**
     * 从Builder创建OrgConfig实例
     * 
     * @param OrgConfigBuilder $builder OrgConfigBuilder实例
     * @throws Exception
     */
    public function __construct(OrgConfigBuilder $builder)
    {
        $this->appId = $builder->getAppId();
        $this->url = $builder->getUrl();
        $this->orgPriKey = $builder->getOrgPriKey();
        $this->orgPubKey = $builder->getOrgPubKey();
        $this->jlpayPubKey = $builder->getJlpayPubKey();
        $this->verifyOrgNo = $builder->getVerifyOrgNo();
        $this->verifyMerchNo = $builder->getVerifyMerchNo();
        $this->cryptoAlg = $builder->getCryptoAlg();
        $this->autoEncrypt = $builder->getAutoEncrypt();
        $this->autoDecrypt = $builder->getAutoDecrypt();
        $this->connectTimeout = $builder->getConnectTimeout();
        $this->readTimeout = $builder->getReadTimeout();
        
        // 解析密钥
        if ($this->orgPriKey && $this->jlpayPubKey) {
            $this->orgPriKeyHex = SmUtils::parsePrivateKey($this->orgPriKey);
            $this->jlpayPubKeyHex = SmUtils::parsePublicKey($this->jlpayPubKey);
        }
        
        // 解析机构公钥
        if ($this->orgPubKey) {
            $this->orgPubKeyHex = SmUtils::parsePublicKey($this->orgPubKey);
        }
    }
    
    /**
     * 获取AppID
     * 
     * @return string
     */
    public function getAppId()
    {
        return $this->appId;
    }
    
    /**
     * 获取请求地址
     * 
     * @return string
     */
    public function getUrl()
    {
        return $this->url;
    }
    
    /**
     * 获取机构私钥
     * 
     * @return string
     */
    public function getOrgPriKey()
    {
        return $this->orgPriKey;
    }
    
    /**
     * 获取机构公钥
     * 
     * @return string
     */
    public function getOrgPubKey()
    {
        return $this->orgPubKey;
    }
    
    /**
     * 获取嘉联公钥
     * 
     * @return string
     */
    public function getJlpayPubKey()
    {
        return $this->jlpayPubKey;
    }
    
    /**
     * 获取机构私钥（16进制）
     * 
     * @return string
     */
    public function getOrgPriKeyHex()
    {
        return $this->orgPriKeyHex;
    }
    
    /**
     * 获取机构公钥（16进制）
     * 
     * @return string
     */
    public function getOrgPubKeyHex()
    {
        return $this->orgPubKeyHex;
    }
    
    /**
     * 获取嘉联公钥（16进制）
     * 
     * @return string
     */
    public function getJlpayPubKeyHex()
    {
        return $this->jlpayPubKeyHex;
    }
    
    /**
     * 获取是否校验机构号
     * 
     * @return bool
     */
    public function isVerifyOrgNo()
    {
        return $this->verifyOrgNo;
    }
    
    /**
     * 获取是否校验商户号
     * 
     * @return bool
     */
    public function isVerifyMerchNo()
    {
        return $this->verifyMerchNo;
    }
    
    /**
     * 获取加密算法
     * 
     * @return string
     */
    public function getCryptoAlg()
    {
        return $this->cryptoAlg;
    }
    
    /**
     * 获取是否自动加密
     * 
     * @return bool
     */
    public function isAutoEncrypt()
    {
        return $this->autoEncrypt;
    }
    
    /**
     * 获取是否自动解密
     * 
     * @return bool
     */
    public function isAutoDecrypt()
    {
        return $this->autoDecrypt;
    }
    
    /**
     * 获取连接超时时间
     * 
     * @return int
     */
    public function getConnectTimeout()
    {
        return $this->connectTimeout;
    }
    
    /**
     * 获取读取超时时间
     * 
     * @return int
     */
    public function getReadTimeout()
    {
        return $this->readTimeout;
    }

    /**
     * 返回一个新的OrgConfigBuilder实例
     * 
     * @return OrgConfigBuilder
     */
    public static function builder()
    {
        return new OrgConfigBuilder();
    }
}

/**
 * 机构配置构建器
 */
class OrgConfigBuilder
{
    /**
     * AppID
     * @var string|null
     */
    private $_appId;
    
    /**
     * 请求地址
     * @var string|null
     */
    private $_url;
    
    /**
     * 机构私钥
     * @var string|null
     */
    private $_orgPriKey;
    
    /**
     * 机构公钥
     * @var string|null
     */
    private $_orgPubKey;
    
    /**
     * 嘉联公钥
     * @var string|null
     */
    private $_jlpayPubKey;
    
    /**
     * 是否校验机构号
     * @var bool
     */
    private $_verifyOrgNo;
    
    /**
     * 是否校验商户号
     * @var bool
     */
    private $_verifyMerchNo;
    
    /**
     * 加密算法
     * @var string
     */
    private $_cryptoAlg;
    
    /**
     * 是否自动加密
     * @var bool
     */
    private $_autoEncrypt;
    
    /**
     * 是否自动解密
     * @var bool
     */
    private $_autoDecrypt;
    
    /**
     * 连接超时时间
     * @var int
     */
    private $_connectTimeout;
    
    /**
     * 读取超时时间
     * @var int
     */
    private $_readTimeout;
    
    /**
     * 初始化Builder属性
     */
    public function __construct()
    {
        $this->_appId = null;
        $this->_url = null;
        $this->_orgPriKey = null;
        $this->_orgPubKey = null;
        $this->_jlpayPubKey = null;
        $this->_verifyOrgNo = true;
        $this->_verifyMerchNo = true;
        $this->_cryptoAlg = "SM2WithSM4";  // 加密算法，默认使用SM2WithSM4
        $this->_autoEncrypt = true;
        $this->_autoDecrypt = true;
        $this->_connectTimeout = 10000;  // 连接超时，单位毫秒
        $this->_readTimeout = 30000;  // 读取超时，单位毫秒
    }
    
    /**
     * 设置AppID
     * 
     * @param string $appId 嘉联分配的AppID
     * @return OrgConfigBuilder
     */
    public function appId($appId)
    {
        $this->_appId = $appId;
        return $this;
    }
    
    /**
     * 设置请求地址
     * 
     * @param string $url 嘉联请求地址
     * @return OrgConfigBuilder
     */
    public function url($url)
    {
        $this->_url = $url;
        return $this;
    }
    
    /**
     * 设置机构私钥
     * 
     * @param string $orgPriKey 机构私钥，PEM格式
     * @return OrgConfigBuilder
     */
    public function orgPriKey($orgPriKey)
    {
        $this->_orgPriKey = $orgPriKey;
        return $this;
    }
    
    /**
     * 设置机构公钥
     * 
     * @param string $orgPubKey 机构公钥，PEM格式
     * @return OrgConfigBuilder
     */
    public function orgPubKey($orgPubKey)
    {
        $this->_orgPubKey = $orgPubKey;
        return $this;
    }
    
    /**
     * 设置嘉联公钥
     * 
     * @param string $jlpayPubKey 嘉联公钥，PEM格式
     * @return OrgConfigBuilder
     */
    public function jlpayPubKey($jlpayPubKey)
    {
        $this->_jlpayPubKey = $jlpayPubKey;
        return $this;
    }
    
    /**
     * 设置是否校验机构号
     * 
     * @param bool $verifyOrgNo 是否校验机构号
     * @return OrgConfigBuilder
     */
    public function verifyOrgNo($verifyOrgNo)
    {
        $this->_verifyOrgNo = $verifyOrgNo;
        return $this;
    }
    
    /**
     * 设置是否校验商户号
     * 
     * @param bool $verifyMerchNo 是否校验商户号
     * @return OrgConfigBuilder
     */
    public function verifyMerchNo($verifyMerchNo)
    {
        $this->_verifyMerchNo = $verifyMerchNo;
        return $this;
    }
    
    /**
     * 设置加密算法
     * 
     * @param string $cryptoAlg 加密算法，目前支持SM2+SM4
     * @return OrgConfigBuilder
     */
    public function cryptoAlg($cryptoAlg)
    {
        $this->_cryptoAlg = $cryptoAlg;
        return $this;
    }
    
    /**
     * 设置是否自动加密敏感字段
     * 
     * @param bool $autoEncrypt 是否自动加密
     * @return OrgConfigBuilder
     */
    public function autoEncrypt($autoEncrypt)
    {
        $this->_autoEncrypt = $autoEncrypt;
        return $this;
    }
    
    /**
     * 设置是否自动解密敏感字段
     * 
     * @param bool $autoDecrypt 是否自动解密
     * @return OrgConfigBuilder
     */
    public function autoDecrypt($autoDecrypt)
    {
        $this->_autoDecrypt = $autoDecrypt;
        return $this;
    }
    
    /**
     * 设置连接超时时间
     * 
     * @param int $connectTimeout 连接超时时间，单位毫秒
     * @return OrgConfigBuilder
     */
    public function connectTimeout($connectTimeout)
    {
        $this->_connectTimeout = $connectTimeout;
        return $this;
    }
    
    /**
     * 设置读取超时时间
     * 
     * @param int $readTimeout 读取超时时间，单位毫秒
     * @return OrgConfigBuilder
     */
    public function readTimeout($readTimeout)
    {
        $this->_readTimeout = $readTimeout;
        return $this;
    }
    
    /**
     * 获取AppID
     * @return string|null
     */
    public function getAppId()
    {
        return $this->_appId;
    }
    
    /**
     * 获取URL
     * @return string|null
     */
    public function getUrl()
    {
        return $this->_url;
    }
    
    /**
     * 获取机构私钥
     * @return string|null
     */
    public function getOrgPriKey()
    {
        return $this->_orgPriKey;
    }
    
    /**
     * 获取机构公钥
     * @return string|null
     */
    public function getOrgPubKey()
    {
        return $this->_orgPubKey;
    }
    
    /**
     * 获取嘉联公钥
     * @return string|null
     */
    public function getJlpayPubKey()
    {
        return $this->_jlpayPubKey;
    }
    
    /**
     * 获取是否校验机构号
     * @return bool
     */
    public function getVerifyOrgNo()
    {
        return $this->_verifyOrgNo;
    }
    
    /**
     * 获取是否校验商户号
     * @return bool
     */
    public function getVerifyMerchNo()
    {
        return $this->_verifyMerchNo;
    }
    
    /**
     * 获取加密算法
     * @return string
     */
    public function getCryptoAlg()
    {
        return $this->_cryptoAlg;
    }
    
    /**
     * 获取是否自动加密
     * @return bool
     */
    public function getAutoEncrypt()
    {
        return $this->_autoEncrypt;
    }
    
    /**
     * 获取是否自动解密
     * @return bool
     */
    public function getAutoDecrypt()
    {
        return $this->_autoDecrypt;
    }
    
    /**
     * 获取连接超时时间
     * @return int
     */
    public function getConnectTimeout()
    {
        return $this->_connectTimeout;
    }
    
    /**
     * 获取读取超时时间
     * @return int
     */
    public function getReadTimeout()
    {
        return $this->_readTimeout;
    }
    
    /**
     * 构建OrgConfig实例
     * 
     * @return OrgConfig
     * @throws ConfigException
     */
    public function build()
    {
        // 验证必需参数
        if (!$this->_appId) {
            throw new ConfigException("appId不能为空");
        }
        if (!$this->_url) {
            throw new ConfigException("url不能为空");
        }
        if (!$this->_orgPriKey) {
            throw new ConfigException("机构私钥不能为空");
        }
        if (!$this->_jlpayPubKey) {
            throw new ConfigException("嘉联公钥不能为空");
        }
        if (!$this->_orgPubKey) {
            throw new ConfigException("机构公钥不能为空");
        }
        
        return new OrgConfig($this);
    }
} 